package club.jdiy.business.mgmt;

import club.jdiy.admin.controller.JDiyAdminCtrl;
import club.jdiy.admin.interceptor.GuestDisabled;
import club.jdiy.business.AppConfig;
import club.jdiy.business.entity.Article;
import club.jdiy.business.service.ArticleService;
import club.jdiy.business.service.SimpleService;
import club.jdiy.business.vo.ArticleVo;
import club.jdiy.core.AppContext;
import club.jdiy.core.base.JDiyBaseService;
import club.jdiy.core.base.JDiyCtrl;
import club.jdiy.core.base.domain.Pager;
import club.jdiy.core.base.domain.Ret;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;

/**
 * 后台管理Controller.
 * <p>
 * 这是文章的管理Controller      (这只是一个演示。主要是编码开发用到。  通过在线开发生成的界面不需要这个东西)
 */
@Controller
@RequestMapping(value = "/mgmt/article")   //注意后台访问地址都要放在/mgmt/路径之下，这样才能被JDiy的后台拦截器拦截，以便进行用户是否登录的权限验证与授权
//推荐的后台路径写为：  /mgmt/实体模块名/业务子页面  这样的格式。 如：  /mgmt/article/ls  表示文章的后台列表管理页。
public class ArticleMgmt
        extends JDiyAdminCtrl<Article, ArticleService> {
    //注意extends后面的内容。所有的后台管理controller都可以是这种写法，不同的controller就把Article换成对应的实体类
    //注意后台管理是extends JDiyAdminCtrl，其它控制器，是JDiyCtrl (没有Admin)

    //......自已添加controller中的业务方法......


    //后台管理，通常90%的情况是一个分页列表管理（列表顶部有各种动态查询条件输入框），和一个添加/修改表单界面。
    //然后就是列表中可能会增加一些操作按钮（如行后面的删除按钮）
    //JDiyAdminCtrl后台控制器已经内置了： 分页列表管理（含动态查询）；表单输入；表单保存；删除数据行，这些常用controller公方法，
    //相应的内置地址请求如下(其中${ctx}是应用程序上下文, {modelName}是当前实体的名称表示，即实体的类名把首字母变成小写)：
    //列表管理：  ${ctx}/mgmt/{modelName}/ls
    //删除数据：  ${ctx}/mgmt/{modelName}/remove
    //表单输入：  ${ctx}/mgmt/{modelName}/in
    //表单保存：  ${ctx}/mgmt/{modelName}/save
    //例如，当前为文章实体，则文章管理列表的地址是： ${ctx}/mgmt/article/ls
    //请求到上面这些地址，会调用JDiyAdminCtrl内置的方法，即您不需要在写这几个页面的Controller方法了。

    //关于view视图层：
    //Controller对应的view层，使用的是freemarker模板。位置在 src/main/templates/mgmt/{modelName}/目录下，
    //如article的列表管理的view位置   src/main/templates/mgmt/article/ls.ftl   (表单就是in.ftl)

    //
    //
    // 当然您有个性需求，可以重写它们对应的方法，如：
    /*@Override
    public String ls(Article qo, String orderField, String orderDirection, Integer pageSize, Integer page, ModelMap map, HttpServletRequest request) {
        map.put("categoryList",categoryService.findAll());//比如要增加一些model到map
        return super.ls(qo, orderField, orderDirection, pageSize, page, map, request);
    }*/
    //当然您也可以自己增加其它控制方法。。。。。


    //××××××××××××××××      以下只是演示（增加的其它方法）。无任何逻辑意义：

    //普通页面显示：
    @RequestMapping("sayHello")
    public String sayHello(ModelMap map, Integer id) {
        //todo something
        service.findById(id).ifPresent(article -> {
            map.put("article", article);
        });
        map.put("myName", "JDiy");
        return "hello.ftl";
    }

    //ajax请求/响应：
    @RequestMapping("doAjaxGetOne")
    public Ret<ArticleVo> doAjaxGetOne(@RequestParam(defaultValue = "1") Integer id) {
        try {
            //todo something
            //这只是一个演示，ajax请求的controller写法。实际就是根据id显示文章概要（标题/id/添加时间）
            Article article = service.findById(id).orElse(null);

            if (article == null) return Ret.fail("没有找到文章。");//普通fail提示信息json返回

            else return Ret.success(new ArticleVo(article));//转成一个vo返回了  正常数据返回

        } catch (Exception ex) {
            return Ret.error(ex);//错误信息返回
        }
    }


    //演示ajax请求返回一个带分页的list数据：
    @RequestMapping("pager_demo")
    public Ret<Pager<ArticleVo>> pager_demo(Article qo, //注意这就是动态查询的条件Model(直接用的实体类。当然您也可以自建其它查询qo对象)
                                            @RequestParam(defaultValue = "10") Integer pageSize,
                                            @RequestParam(defaultValue = "1") Integer page
    ) {
        try {
            Pager<Article> pager = service.findPager(pageSize, page, qo);

            return Ret.success(pager.to(ArticleVo::new));//一键将Article实体分页对象转成一个Vo分页对象
            //上行使用了lambda表达式一键转换,原生写法如下：
            /*
            List<ArticleVo> list= new ArrayList<>();
            for(Article a:pager.getItems()){
                list.add(new ArticleVo(a));
            }
            return Ret.success(new Pager<>(page,pageSize,pager.getRowCount(),list));
            */


        } catch (Exception ex) {
            return Ret.error(ex);//错误信息返回
        }
    }


    //如果要查询其它实体，引入其它实体对应的service或dao即可,如：
    @Resource
    private SimpleService simpleService;


}
